---
title: "Toolchains"
slug: /features/toolchains
description: "Install multiple reusable modules as toolchains to extend your workflows"
toc_max_heading_level: 2
---

Dagger toolchains allow you to install and use multiple Dagger modules as composable extensions to your own module. Unlike dependencies or blueprints, toolchains provide a flexible way to combine functionality from multiple modules, making them available as namespaced functions within your module's API.

## Key Concepts

### What are Toolchains?

Toolchains are Dagger modules that are installed into your module to provide additional functionality without needing to integrate with your module's SDK or blueprint. When you install a toolchain:

- The toolchain's functions become available in your module's API as a namespaced field
- Multiple toolchains can be installed simultaneously
- Toolchains work with modules that have an SDK, use a blueprint, or neither
- Each toolchain maintains its own context and can access files from your module's directory

## Use Cases

### Platform Engineering

Toolchains are ideal for platform teams providing standardized tools to application teams:

```shell
# Platform team publishes toolchains
github.com/platform/linter
github.com/platform/security-scanner
github.com/platform/deployer

# App teams install them
dagger toolchain install github.com/platform/linter
dagger toolchain install github.com/platform/security-scanner
dagger toolchain install github.com/platform/deployer

dagger call linter lint
```

### CI/CD Composition

Build a complete CI/CD pipeline by composing toolchains:

```shell
dagger toolchain install github.com/example/tester
dagger toolchain install github.com/example/builder
dagger toolchain install github.com/example/publisher
dagger toolchain install github.com/example/notifier
```

Run your entire pipeline:

```shell
dagger call tester test && \
dagger call builder build && \
dagger call publisher publish && \
dagger call notifier notify --status success
```

### Polyglot Projects

Use toolchains written in different languages without worrying about compatibility:

```shell
# Go toolchain
dagger toolchain install github.com/example/go-linter

# Python toolchain
dagger toolchain install github.com/example/python-tester

# TypeScript toolchain
dagger toolchain install github.com/example/ts-bundler
```

All toolchains work together seamlessly regardless of their implementation language.


## Installing Toolchains

### Install a Toolchain

To install a toolchain in your module, use the `dagger toolchain install` command:

```shell
dagger toolchain install github.com/example/toolchain
```

You can install toolchains from:
- **GitHub repositories**: `github.com/user/repo/path`
- **Local paths**: `./path/to/toolchain` or `/absolute/path`
- **Git URLs**: Any valid Git URL with optional version tags

### Install with a Custom Name

By default, the toolchain is accessible using its module name. If the module name is not suitable or conflicts with a function in your module, you can specify a custom name:

```shell
dagger toolchain install github.com/example/toolchain --name mytool
```

### Install Multiple Toolchains

You can install as many toolchains as you need:

```shell
dagger toolchain install github.com/example/hello
dagger toolchain install github.com/example/builder
dagger toolchain install github.com/example/tester
```

Each toolchain becomes available under its own namespace in your module's API.

## Using Toolchains

### Calling Toolchain Functions

Once installed, toolchain functions are available through the toolchain's namespace. For example, if you installed a toolchain named `hello`:

```shell
dagger call hello message
```

If the toolchain has a constructor that accepts parameters, you can provide them:

```shell
dagger call hello --config myconfig.txt field-config
```

### Accessing Module Files from Toolchains

Toolchains have access to your module's context directory. This means a toolchain can reference files in your module using default path parameters or explicit file arguments:

```go
// In a toolchain module
func (m *Hello) AppConfig(
    ctx context.Context,
    // +defaultPath="./app-config.txt"
    config *dagger.File,
) (string, error) {
    return config.Contents(ctx)
}
```

When called from your module, `app-config.txt` will be resolved from your module's directory, not the toolchain's repository.

## Toolchains with SDKs

Toolchains work seamlessly with modules that have an SDK. Your module can implement its own functions while also exposing toolchain functions:

### Example: Go Module with Toolchain

Initialize a Go module and install a toolchain:

```shell
dagger init --sdk=go
dagger toolchain install github.com/example/hello
```

Now you can call both your module's functions and the toolchain's functions:

```shell
# Call your module's function
dagger call container-echo --string-arg "hello" stdout

# Call the toolchain's function
dagger call hello message
```

## Toolchains with Blueprints

Toolchains can be combined with blueprints, giving you the best of both worlds: a blueprint provides the core template for your module, while toolchains add supplementary functionality.

```shell
dagger init --blueprint=github.com/example/app-blueprint
dagger toolchain install github.com/example/linter
dagger toolchain install github.com/example/deployer
```

This configuration allows you to:
- Use the blueprint's functions as your module's primary API
- Access additional toolchain functions for auxiliary tasks
- Keep your module focused while still having access to extended functionality

## Toolchains without an SDK

Even if your module doesn't use an SDK or blueprint, toolchains are valuable. They let you compose functionality from multiple modules without writing any code:

```shell
dagger init
dagger toolchain install github.com/example/hello
dagger toolchain install github.com/example/builder
dagger toolchain install github.com/example/tester
```

Your module becomes a collection point for these toolchains, making their combined functionality available through a single interface:

```shell
dagger call hello message
dagger call builder build --source ./app
dagger call tester test --source ./app
```

## Filtering Toolchain Checks

When you install a toolchain that includes checks, all checks from that toolchain are automatically included when you run `dagger check`. However, there may be times when you want to exclude certain checks from a toolchain while keeping others. The `ignoreChecks` configuration allows you to selectively filter out specific checks from a toolchain.

### Using ignoreChecks

To ignore checks from a toolchain, you can manually edit your `dagger.json` configuration file to add an `ignoreChecks` array to the toolchain configuration:

```json
{
  "name": "my-app",
  "engineVersion": "v0.16.0",
  "toolchains": [
    {
      "name": "linter",
      "source": "github.com/example/linter",
      "ignoreChecks": [
        "failing-check",
        "optional-check"
      ]
    }
  ]
}
```

The check patterns in `ignoreChecks` are scoped to the toolchain, so you don't need to include the toolchain name prefix. For example, if a toolchain named `linter` has a check `linter:code-style`, you would only specify `code-style` in the `ignoreChecks` array.

### Using Glob Patterns

The `ignoreChecks` configuration supports glob patterns, allowing you to ignore multiple checks that match a pattern:

```json
{
  "name": "my-app",
  "engineVersion": "v0.16.0",
  "toolchains": [
    {
      "name": "security-scanner",
      "source": "github.com/example/security",
      "ignoreChecks": [
        "experimental-*",
        "*-beta"
      ]
    }
  ]
}
```

This is useful when you want to:
- Exclude all experimental or beta checks: `experimental-*`, `*-beta`
- Skip checks for specific components: `frontend-*`, `*-integration`
- Ignore checks by category: `style-*`, `performance-*`

### When to Use ignoreChecks

Common use cases for ignoring toolchain checks include:

- **Gradual adoption**: Ignore failing checks while your codebase is being updated to meet new standards
- **Environment-specific checks**: Skip checks that don't apply to certain projects or environments
- **Experimental features**: Exclude experimental or beta checks that may not be stable
- **Performance optimization**: Skip expensive checks that aren't critical for your workflow

### Viewing Active Checks

To see which checks are available after applying `ignoreChecks` filters, use the `dagger check -l` command:

```shell
dagger check -l
```

This will list all checks that will run, excluding any that match your `ignoreChecks` patterns.

## Best Practices

### Keep Toolchains Focused

Each toolchain should provide a cohesive set of related functions. Instead of creating a monolithic "everything" toolchain, create smaller, focused toolchains that teams can mix and match.

### Namespace Considerations

When naming toolchains (especially with `--name`), choose clear, descriptive names that won't conflict with your module's own functions or other toolchains.

### Use ignoreChecks Sparingly

While `ignoreChecks` provides flexibility, it's generally better to work with toolchain maintainers to address problematic checks at the source. Use `ignoreChecks` as a temporary measure or for legitimate environment-specific filtering, not as a way to permanently suppress important checks.

## Conclusion

Toolchains provide a powerful way to compose and extend Dagger modules. Whether you're building a platform, assembling a CI/CD pipeline, or creating a collection of useful utilities, toolchains give you the flexibility to combine functionality from multiple sources while maintaining clean, organized APIs.
